using System;

namespace SharpMud.MudLib.SAMPLE.Commands
{
    //public interface ICmdExecContext : SharpMud.Server.Systems.Scripting.Processing.Source.
    //{		
    //    /// <summary>
    //    /// The character that is executing this command.
    //    /// </summary>
    //    Entities.ICharacter Actor		{get;}

    //    /// <summary>
    //    /// The character whose administrative authority is used to execute this command.
    //    /// </summary>
    //    Entities.ICharacter	Authority	{get;}

    //    /// <summary>
    //    /// The mud server
    //    /// </summary>
    //    SAMPLE.MudLibRoot MudServer		{get;}
    //    /// <summary>
    //    /// As if this command were (and it might have been) called from a player prompt,
    //    /// this is the first word in the command line given. This is the portion that
    //    /// is to be compared against a CommandMetadatum's command matchers.
    //    /// </summary>
    //    string CommandLineHead {get;}

    //    /// <summary>
    //    /// As if this command were (and it might have been) called from a player prompt,
    //    /// this everything after the first word and consecutive whitespace on that command line.
    //    /// It contains parameters that the command needs to execute.
    //    /// </summary>
    //    string CommandLineTail {get;}

    //    /// <summary>
    //    /// As if this command were (and it might have been) called from a player prompt,
    //    /// this is the entire command line.
    //    /// </summary>
    //    string FullCommandLine {get;}

    //    /// <summary>
    //    /// This method throws an exception if this CmdExecContext instance's 'actor' is not a player.
    //    /// </summary>
    //    void RequireActorIsPlayer();
    //}

	public class CommandExecutionContext : SharpMud.Server.Systems.Scripting.Runtime.ScriptExecutionContext
	{
        #region Contructors
		public CommandExecutionContext(CommandManager host, Entities.ICharacter actor, string fullCommandLine)
			:this(host,actor,actor,fullCommandLine)
		{
		}

		public CommandExecutionContext(CommandManager host, Entities.ICharacter actor, Entities.ICharacter authority, string fullCommandLine)
            :base()
		{
            
			base["_Host"] = host;
			base["_Actor"] = actor;
			base["_Authority"] = authority;
			base["_FullCommandLine"] = fullCommandLine.Trim();
			base["_TailStart"]  = DetermineTailStart(fullCommandLine);
			base["_Host"] = host;
		}
		#endregion

        private int _TailStart
        {
            get
            {
                return (base["_TailStart"] as int);
            }
        }

		#region Public Propertes
		public CommandManager Host
		{
			get
			{
				return (base["_Host"] as CommandManager);
			}
		}
		#endregion

		#region Private Methods
		private static string FirstWord(string trimmedCommandLine)
		{
			string s = trimmedCommandLine;
	
			int i=0;
			
			//Find the start of the whitespace after the first word
			for(i=0;
				i<s.Length && !Char.IsWhiteSpace(s[i]);
				i++);

			//So i is the first character after the first word
			//eg:
			// r u n   s o u t h
			//       \
			//        'i'==3
			return s.Substring(0,i);
		}

		private static int DetermineTailStart(string trimmedCommandLine)
		{
			string s = trimmedCommandLine;
	
			int i=0;
			
			//Find the start of the whitespace after the first word
			for(i=0;
				i<s.Length && !Char.IsWhiteSpace(s[i]);
				i++);

			//Find the first non-whitespace character after this whitespace
			for(;
				i<s.Length && Char.IsWhiteSpace(s[i]);
				i++);

			return i;
		}
		#endregion

		#region ICmdExecContext Members
		public SAMPLE.MudLibRoot MudServer
		{
			get
			{
				return Host.HostMud;
			}
		}
		public SharpMud.MudLib.SAMPLE.Entities.ICharacter Actor
		{
			get
			{
				return (base["_Actor"] as SharpMud.MudLib.SAMPLE.Entities.ICharacter);
			}
		}

		public SharpMud.MudLib.SAMPLE.Entities.ICharacter Authority
		{
			get
			{
				return (base["_Authority"] as SharpMud.MudLib.SAMPLE.Entities.ICharacter);
			}
		}
		public string CommandLineHead
		{
			get
			{
				return FirstWord(FullCommandLine);
			}
		}

		public string CommandLineTail
		{
			get
			{
				return FullCommandLine.Substring(_TailStart,FullCommandLine.Length-_TailStart);
			}
		}

		public string FullCommandLine
		{
			get
			{
				return (base["_FullCommandLine"] as string);
			}
		}
		#endregion

		public void RequireActorIsPlayer()
		{
			if(this.Actor.GetType() is Entities.PlayerCharacter)
				return;
			else
				throw new InvalidOperationException("This command requires that the actor be a player character!");
		}
	}
}